package com.raingo.imrp;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.renderscript.Sampler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    private static final String TAG = "rain-im";

    @BindView(R.id.main_tv_showinfo)
    TextView mTvShowInfo;
    @BindView(R.id.main_lv_plays)
    ListView mLvPlays;
    @BindView(R.id.main_btn_record)
    Button mBtnRecord;

    private ExecutorService mExecutorService;

    private MediaRecorder mediaRecorder;
    private File mediaFile;
    private File audioFile;

    private final String MediaFilePath = "/sdcard/imrp/mediafile/";
    private final String AudioFilePath = "/sdcard/imrp/audiofile/";

    //false -> media , true -> audio
    private boolean useMediaOrAudio = false;

    private long startRecordTime = 0, stopRecordTime = 0;

    private final Handler myHandler = new MyHandler(this);
    private final int MSG_WHAT_RECORD_ERR = 1;
    private final int MSG_WHAT_RECORD_TIME_LESS = 2;
    private final int MSG_WHAT_RECORD_SUCCESS = 3;
    private final int MSG_WHAT_RECORD_STOP_ERR = 4;

    private volatile boolean isRecording;//volatile  保证多线程内存同步
    private byte[] mBuffer;
    private final int BUFFER_SIZE = 2048;
    private FileOutputStream fileOutputStream;
    private AudioRecord audioRecord;

    private int audioSource = MediaRecorder.AudioSource.MIC;
    private int sampleRate = 44100;
    private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
    private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ButterKnife.bind(this);

        mBuffer = new byte[BUFFER_SIZE];

        mBtnRecord.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (useMediaOrAudio) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            break;
                        case MotionEvent.ACTION_UP:
                        case MotionEvent.ACTION_CANCEL:
                            if (isRecording) {
                                //关闭录音
                                isRecording = false;

                            } else {
                                //开始录音
                                isRecording = true;
                                startRecord();
                            }

                            break;
                    }
                } else {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            Log.d(TAG, "onTouch: action down");
                            startRecord();
                            break;
                        case MotionEvent.ACTION_UP:
                            Log.d(TAG, "onTouch: action up");
                        case MotionEvent.ACTION_CANCEL:
                            Log.d(TAG, "onTouch: action cancel");
                            stopRecord();
                            break;
                    }
                }

                return true;
            }

        });


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        //录音jni层不具备线程安全,使用单线程.
        mExecutorService = Executors.newSingleThreadExecutor();

        //创建一个文件夹存放音频文件
        new File(MediaFilePath).mkdirs();
        new File(AudioFilePath).mkdirs();
    }


    private void startRecord() {
        mBtnRecord.setText(R.string.do_record);

        //后台提交录音任务
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
                //release recorder
                releaseRecorder();

                if (!tryStartRecord()) {
                    recordFail();
                }
            }
        });
    }

    private void stopRecord() {
        mBtnRecord.setText(R.string.start_record);

        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {

                if (!doStopRecord()) {
                    recordFail();
                }

                releaseRecorder();
            }
        });
    }

    private void recordFail() {
        Log.d(TAG, "recordFail: ");

        if (useMediaOrAudio) {
            isRecording = false;

        } else {
            mediaRecorder = null;
        }

        Message msg = Message.obtain();
        msg.what = MSG_WHAT_RECORD_ERR;
        myHandler.sendMessage(msg);
    }

    private boolean tryStartRecord() {
        Log.d(TAG, "tryStartRecord: useMediaOrAudio " + useMediaOrAudio);
        if (useMediaOrAudio) {
//            audioFile.getParentFile().mkdirs();//oncreate 中创建了
            try {
                startRecordTime = System.currentTimeMillis();
                audioFile = new File(AudioFilePath + startRecordTime + ".pcm");
                audioFile.createNewFile();

                fileOutputStream = new FileOutputStream(audioFile);

                //计算audiorecord 内部 缓存区最小值
                int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
                //buffer 不能小于最低要求,也不能小于我们每次读取的大小
                audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, Math.max(minBufferSize, BUFFER_SIZE));

                while (isRecording) {
                    int read = audioRecord.read(mBuffer, 0, BUFFER_SIZE);
                    if (read > 0) {
                        fileOutputStream.write(mBuffer, 0, read);
                    } else {
                        //读取失败
                        isRecording = false;
                        return false;
                    }
                }

                return doStopRecord();
            } catch (Exception e) {
                e.printStackTrace();
                isRecording = false;
                return false;
            } finally {
                releaseRecorder();
            }
        } else {
            try {
                mediaRecorder = new MediaRecorder();

                startRecordTime = System.currentTimeMillis();

                mediaFile = new File(MediaFilePath + startRecordTime + ".mp4");

                mediaFile.createNewFile();

                //从麦克风采集音频
                mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                //输出格式mp4
                mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                //android设备支持的采样频率
                mediaRecorder.setAudioSamplingRate(44100);
                //通用编码格式AAC
                mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
                //音质频率
                mediaRecorder.setAudioEncodingBitRate(96000);

                mediaRecorder.setOutputFile(mediaFile.getAbsolutePath());

                //开始录音
                mediaRecorder.prepare();
                mediaRecorder.start();
            } catch (IOException e) {
                e.printStackTrace();
                //录音文件创建失败
                startRecordTime = 0;
                return false;
            }
        }
        return true;
    }

    private boolean doStopRecord() {
        Log.d(TAG, "doStopRecord: ");
        Message msg = Message.obtain();

        try {
            if (useMediaOrAudio) {
                audioRecord.release();
                releaseRecorder();
                fileOutputStream.close();
            } else {

                mediaRecorder.stop();
            }
        } catch (Exception e) {
            e.printStackTrace();
            msg.what = MSG_WHAT_RECORD_STOP_ERR;
            myHandler.sendMessage(msg);
            return false;
        }

        stopRecordTime = System.currentTimeMillis();

        //只接受3s以上的录音
        if ((stopRecordTime - startRecordTime) / 1000 > 3) {

            msg.what = MSG_WHAT_RECORD_SUCCESS;
        } else {
            msg.what = MSG_WHAT_RECORD_TIME_LESS;
        }
        myHandler.sendMessage(msg);
        return true;
    }

    private void releaseRecorder() {
        Log.d(TAG, "releaseRecorder: ");
        if (useMediaOrAudio) {
            if (null != audioRecord) {
                audioRecord.release();
                audioRecord = null;
            }
        } else {
            if (mediaRecorder != null) {
                mediaRecorder.release();
                mediaRecorder = null;
            }
        }

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mExecutorService.shutdownNow();//避免内存泄漏
        releaseRecorder();
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    class MyHandler extends Handler {
        WeakReference<Activity> mActivity;

        MyHandler(Activity activity) {
            mActivity = new WeakReference<Activity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG, "handleMessage: what" + msg.what);
            if (mActivity.get() != null) {
                switch (msg.what) {
                    case MSG_WHAT_RECORD_ERR:
                        mTvShowInfo.setText(R.string.msg_what_record_err);
                        Toast.makeText(mActivity.get().getApplicationContext(), R.string.msg_what_record_err, Toast.LENGTH_SHORT).show();
                        mBtnRecord.setText("点击开始录音");
                        break;
                    case MSG_WHAT_RECORD_TIME_LESS:
                        mTvShowInfo.setText(R.string.msg_what_record_time_less);

                        break;
                    case MSG_WHAT_RECORD_SUCCESS:
                        mTvShowInfo.setText(R.string.msg_what_record_success);
                        break;
                    case MSG_WHAT_RECORD_STOP_ERR:
                        mTvShowInfo.setText(R.string.msg_what_record_stop_err);
                        break;
                }
            }
        }
    }
}
